package com.cmwa.scbp.sys.msg.adapter.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cmwa.scbp.sys.msg.adapter.EmailMessageService;
import com.cmwa.scbp.sys.msg.adapter.OperationMessageCallback;
import com.cmwa.scbp.sys.msg.vo.ManualOperationParamsVo;
import com.cmwa.scbp.sys.msg.vo.MsgBatchVo;
import com.cmwa.scbp.sys.msg.vo.MsgConfVo;
import com.cmwa.scbp.sys.msg.vo.MsgExceptionVo;
import com.cmwa.scbp.sys.msg.vo.MsgSendVo;
import com.cmwa.scbp.sys.msg.vo.MsgWaitSendVo;
import com.cmwa.scbp.utils.DateUtils;
import com.cmwa.scbp.utils.EmailUtil;
import com.cmwa.scbp.utils.ExceptionUtil;
import com.cmwa.scbp.utils.guava.predicate.NotEmptyStrPredicate;
import com.google.common.base.Joiner;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

/**
 * 邮件模板实现代理类
 * 
 * @author pangtf
 */
@SuppressWarnings("deprecation")
public class EmailMessageTemplateDelegate {
	
	private static Logger logger = LoggerFactory.getLogger(EmailMessageTemplateDelegate.class);
	
	// 发送类型
	private final String operationType;
	// 发送成功回调类
	private OperationMessageCallback messageCallback;

	protected EmailMessageService emailMessageService;
	
	public EmailMessageTemplateDelegate(String operationType, EmailMessageService emailMessageService) {
		this.operationType = operationType;
		this.emailMessageService = emailMessageService;
	}

	public EmailMessageTemplateDelegate(String operationType, EmailMessageService emailMessageService, OperationMessageCallback successCallback) {
		this.operationType = operationType;
		this.emailMessageService = emailMessageService;
		this.messageCallback = successCallback;
	}

	/**
	 * 获取消息配置
	 */
	public MsgConfVo obtainMsgConf(ManualOperationParamsVo params) {
		return emailMessageService.getMessageOperationService().queryMsgConfByMsgCode(StringUtils.trimToEmpty(params.getMsgCode()));
	}

	public boolean saveNewMessage(List<MsgWaitSendVo> vos, ManualOperationParamsVo params) {
		if (vos != null && vos.size() > 0) {
			int i = 0;
			for (MsgWaitSendVo vo : vos) {
				i += emailMessageService.getMessageOperationService().saveMsgWaitSendVo(vo);
			}
			if (i > 0) {
				return true;
			} else {
				return false;
			}
		}
		return true;
	}

	public void sendMessageAsyn(List<MsgWaitSendVo> vos, ManualOperationParamsVo params) {
		SendEmailAsynThread asyn = new SendEmailAsynThread(vos, params);
		asyn.start();

	}

	/**
	 * 发送邮件
	 * 
	 * @param vos
	 * @param params
	 * @return
	 */
	public boolean sendMessage(List<MsgWaitSendVo> vos, ManualOperationParamsVo params) throws Exception{
		long start = new Date().getTime();
		String startdate = DateUtils.getNowStr(null);

		String r = "没有邮件需要发送";

		List<MsgSendVo> exceptions = new ArrayList<MsgSendVo>();

		List<MsgSendVo> rst = new ArrayList<MsgSendVo>();

		if (vos != null && vos.size() > 0) {

			int s = 0;
			int f = 0;

			for (MsgWaitSendVo dto : vos) {
				String msg = "SUCCESS";
				List<Map<String, String>> attList = null;
				try {
					attList = null;//emailMessageService.getAttachService().getAttachments(dto.getAttids());
					
					// 获取邮箱的代码前置，抽取移到com.cmwa.cbp.sys.msg.adapter.impl.EmailMessageTemplateDelegate.obtainEmailAddress
					List<String> sb_r = dto.getRecipients();
					List<String> sb_c = dto.getCcs();
					if (CollectionUtils.isEmpty(sb_r) && CollectionUtils.isEmpty(sb_c)) {
						continue;
					}

					msg = EmailUtil.sendMail(params.getNickName(),params.getThirdAddressor(),dto.getTitle(), EmailUtil.EMAIL_CONTENTTYPE_HTML, dto.getContent(), sb_r.toArray(new String[sb_r.size()]), sb_c.toArray(new String[sb_c.size()]), attList, dto.getAttFiles());

				} catch (Exception ex) {
					msg = ExceptionUtil.obtainStackTrace(ex);
					logger.error("mail send exception:", ex);
					throw ex;
				}

				MsgSendVo msVo = new MsgSendVo();
				msVo.setWid(dto.getId());
				msVo.setEmpIds(StringUtils.isBlank(dto.getEmpIds())? "SYSTEM":dto.getEmpIds());
				msVo.setEmpIdsC(dto.getEmpIdsC());
				msVo.setType(dto.getType());
				msVo.setTitle(dto.getTitle());
				msVo.setContent(dto.getContent());
				msVo.setAttids(dto.getAttids());
				msVo.setPubEmailIds(dto.getPubEmailIds());
				msVo.setPubEmailIdsC(dto.getPubEmailIdsC());
				msVo.setMsgCode(params.getMsgCode());
				msVo.setRecipients(Joiner.on(";").join(dto.getRecipients()));
				msVo.setCc(Joiner.on(";").join(dto.getCcs()));

				msVo.setCreateId(dto.getCreateId());
				msVo.setCreateDate("");
				msVo.setSendId(StringUtils.trimToEmpty(params.getEmpId()));
				msVo.setMsgBatchId(dto.getId());

				if ("SUCCESS".equals(msg)) {
					msVo.setStatus("NORMAL");
					if (messageCallback != null) {
						messageCallback.onSuccessCallback(dto);
					}
					s++;
				} else {
					msVo.setStatus("EXCEPTION");
					f++;
					MsgExceptionVo eptVo = new MsgExceptionVo();
					eptVo.setException(msg);
					msVo.setException(eptVo);
					exceptions.add(msVo);
				}

				rst.add(msVo);

				/*if (attList != null && attList.size() > 0) {
					emailMessageService.getAttachService().updateAttachFilePathByAttId(attList);
				}*/

			}

			r = "成功[" + s + "]封邮件,异常[" + f + "]封邮件";

		}

		String enddate = DateUtils.getNowStr(null);
		long end = new Date().getTime();

		MsgBatchVo bv = new MsgBatchVo();
		bv.setType(operationType);
		bv.setStartTime(startdate);
		bv.setEndTime(enddate);
		bv.setElapsedTime((end - start) + "");
		bv.setRst(r);
		emailMessageService.getMsgBatchService().saveMsgBatchVo(bv);

		if (rst.size() > 0) {
			for (MsgSendVo v : rst) {
				v.setMsgBatchId(bv.getId());
				v.setCreateId("system");
				emailMessageService.getMsgSendService().create(v);
			}
		}

		if (exceptions.size() > 0) {
			for (MsgSendVo eptVo : exceptions) {

				MsgExceptionVo ept = new MsgExceptionVo();
				ept.setException(eptVo.getException().getException());
				ept.setMsgBatchId(bv.getId());
				ept.setMsgSendId(eptVo.getId());

				emailMessageService.getMsgExceptionService().create(ept);
			}
		}

		return true;
	}

	/**
	 * 获取员工信息所对应的邮箱
	 */
	public Map<String, List<Map<String, String>>> obtainEmailAddressByEmpIds(Map<String, List<String>> empIds) {
		Map<String, List<Map<String, String>>> kv = new HashMap<String, List<Map<String, String>>>();
		if (empIds != null && empIds.get("R") != null && empIds.get("R").size() > 0) {
			String[] param = new String[empIds.get("R").size()];
			empIds.get("R").toArray(param);
			List<Map<String, String>> r = emailMessageService.getMessageOperationService().obtainEmailAddressByEmpIds(param);
			kv.put("R", r);
		}
		if (empIds != null && empIds.get("C") != null && empIds.get("C").size() > 0) {
			String[] param = new String[empIds.get("C").size()];
			empIds.get("C").toArray(param);
			List<Map<String, String>> c = emailMessageService.getMessageOperationService().obtainEmailAddressByEmpIds(param);
			kv.put("C", c);
		}
		return kv;
	}

	/**
	 * 查询消息配置人员的具体信息
	 */
	public Map<String, List<String>> obtainMsgEmpsConf(ManualOperationParamsVo params) {
		Map<String, List<String>> rst = new HashMap<String, List<String>>();

		List<Map<String, String>> confEmps = emailMessageService.getMessageOperationService().queryMsgEmpConfByMsgCode(StringUtils.trimToEmpty(params.getMsgCode()));
		// 获取特殊人员
		List<Map<String, String>> sepcials = emailMessageService.obtainSpecialPerson(params);
		
		boolean isExistsM = false;  // 收件人存在主管
		boolean isExistsS = false;  // 收件人存在指定处理人
		boolean isExistsD = false;  // 收件人存在默认处理人
		boolean isExistsT = false;  // 收件人存在转办委托人

		boolean isExistsM_C = false;  // 抄送人存在主管
		boolean isExistsS_C = false;  // 抄送人存在指定处理人
		boolean isExistsD_C = false;  // 抄送人存在默认处理人
		boolean isExistsT_C = false;  // 抄送人存在转办委托人

		List<String> r = new ArrayList<String>();
		List<String> c = new ArrayList<String>();

		Iterator<Map<String, String>> itr = confEmps.iterator();

		while (itr.hasNext()) {
			Map<String, String> tmp = itr.next();
			String empId = StringUtils.trimToEmpty(tmp.get("EMPID"));
			String empType = StringUtils.trimToEmpty(tmp.get("EMP_TYPE"));
			if ("M".equalsIgnoreCase(empId.trim()) && "R".equalsIgnoreCase(empType.trim())) {
				isExistsM = true;
			} else if ("M".equalsIgnoreCase(empId.trim()) && "C".equalsIgnoreCase(empType.trim())) {
				isExistsM_C = true;
			} else if ("S".equalsIgnoreCase(empId.trim()) && "R".equalsIgnoreCase(empType.trim())) {
				isExistsS = true;
			} else if ("S".equalsIgnoreCase(empId.trim()) && "C".equalsIgnoreCase(empType.trim())) {
				isExistsS_C = true;
			} else if ("D".equalsIgnoreCase(empId.trim()) && "R".equalsIgnoreCase(empType.trim())) {
				isExistsD = true;
			} else if ("D".equalsIgnoreCase(empId.trim()) && "C".equalsIgnoreCase(empType.trim())) {
				isExistsD_C = true;
			} else if ("T".equalsIgnoreCase(empId.trim()) && "R".equalsIgnoreCase(empType.trim())) {
				isExistsT = true;
			} else if ("T".equalsIgnoreCase(empId.trim()) && "C".equalsIgnoreCase(empType.trim())) {
				isExistsT_C = true;
			} else if ("R".equalsIgnoreCase(empType.trim())) {  // 收件人
				r.add(empId);
			} else if ("C".equalsIgnoreCase(empType.trim())) {  // 抄送人
				c.add(empId);
			} 
		}
		
		if (isExistsM || isExistsS || isExistsD || isExistsT) {
			if (sepcials != null && sepcials.size() > 0) {

				int size = sepcials.size();
				int count = 0;
				for (int i = 0; i < size; i++) {
					count = 0;
					Map<String, String> cp = sepcials.get(i);
					String empType = StringUtils.trimToEmpty(cp.get("EMPTYPE"));
					String empId = StringUtils.trimToEmpty(cp.get("EMPID"));
					if (isExistsM && "M".equalsIgnoreCase(empType)) {
						for (String tmp : r) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							r.add(empId);
						}
					}
					if (isExistsS && "S".equalsIgnoreCase(empType)) {
						for (String tmp : r) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							r.add(empId);
						}
					}
					if (isExistsD && "D".equalsIgnoreCase(empType)) {
						for (String tmp : r) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							r.add(empId);
						}
					}
					if (isExistsT && "T".equalsIgnoreCase(empType)) {
						for (String tmp : r) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							r.add(empId);
						}
					}
				}

			}
		}

		if (isExistsM_C || isExistsS_C || isExistsD_C || isExistsT_C) {
			if (sepcials != null && sepcials.size() > 0) {

				int size = sepcials.size();
				int count = 0;
				for (int i = 0; i < size; i++) {
					count = 0;
					Map<String, String> cp = sepcials.get(i);
					String empType = StringUtils.trimToEmpty(cp.get("EMPTYPE"));
					String empId = StringUtils.trimToEmpty(cp.get("EMPID"));
					if (isExistsM_C && "M".equalsIgnoreCase(empType)) {
						for (String tmp : c) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							if (empId != null && !"".equals(empId)) {
								c.add(empId);
							}

						}
					}
					if (isExistsS_C && "S".equalsIgnoreCase(empType)) {
						for (String tmp : c) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							if (empId != null && !"".equals(empId)) {
								c.add(empId);
							}
						}
					}
					if (isExistsD_C && "D".equalsIgnoreCase(empType)) {
						for (String tmp : c) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							if (empId != null && !"".equals(empId)) {
								c.add(empId);
							}
						}
					}
					if (isExistsT_C && "T".equalsIgnoreCase(empType)) {
						for (String tmp : c) {
							if (empId.equalsIgnoreCase(tmp)) {
								count++;
							}
						}
						if (count == 0) {
							if (empId != null && !"".equals(empId)) {
								c.add(empId);
							}
						}
					}
				}

			}
		}
		rst.put("R", r);
		rst.put("C", c);

		return rst;
	}
	
	/**
	 * 抽取根据待发送邮件对象MsgWaitSendVo中EmpIds、EmpIdsC获取对应员工的邮箱，并合并到vo中Emails、PubEmails、PubEmailsC
	 * 设置在待发送Vo的Recipients、ccs中
	 * @param vos
	 * @throws Exception
	 */
	protected boolean obtainEmailAddress(List<MsgWaitSendVo> vos) {
		for (MsgWaitSendVo dto : vos) {
			List<String> sb_r = new ArrayList<String>();
			List<String> sb_c = new ArrayList<String>();
			
			// 收件人邮箱
			String emailsSetting = dto.getEmails();
			if(emailsSetting != null && !"".equalsIgnoreCase(emailsSetting)){
				sb_r.addAll(Arrays.asList(emailsSetting.split(",")));
			}

			// 根据empId查询邮箱
			String emails = getEmailAddressByIds(dto.getEmpIds());
			
			// empId邮箱
			if (emails != null && !"".equalsIgnoreCase(emails) && !sb_r.contains(emails)) {
				sb_r.addAll(Arrays.asList(emails.split(",")));
			}
			
			// 公共邮箱
			if (dto.getPubEmails() != null && !"".equalsIgnoreCase(dto.getPubEmails()) && !sb_r.contains(dto.getPubEmails())) {
				sb_r.addAll(Arrays.asList(dto.getPubEmails().split(",")));
			}
			
			// empId 抄送人
			String emailsc = getEmailAddressByIds(dto.getEmpIdsC());
			if (emailsc != null && !"".equalsIgnoreCase(emailsc)) {
				sb_c.addAll(Arrays.asList(emailsc.split(",")));
			}
			
			// 公共邮箱抄送人
			if (dto.getPubEmailsC() != null && !"".equalsIgnoreCase(dto.getPubEmailsC()) && !sb_c.contains(dto.getPubEmailsC())) {
				sb_c.addAll(Arrays.asList(dto.getPubEmailsC().split(",")));
			}

			// 过滤空值
			sb_r = Lists.newArrayList(Collections2.filter(sb_r, new NotEmptyStrPredicate()));
			sb_c = Lists.newArrayList(Collections2.filter(sb_c, new NotEmptyStrPredicate()));
			
			Set<String> rSet = new HashSet<String>();
			// 去重
			Iterator<String> it = sb_r.iterator();
			while (it.hasNext()) {
				if (!rSet.add(it.next())) {
					it.remove();
				}
			}
			
			rSet.clear();
			// 去重
			it = sb_c.iterator();
			while (it.hasNext()) {
				if (!rSet.add(it.next())) {
					it.remove();
				}
			}
			
			// 排序，为了过滤器SQL便于比较
			Collections.sort(sb_r);
			Collections.sort(sb_c);
			
			dto.setRecipients(sb_r);
			dto.setCcs(sb_c);
			
			if (CollectionUtils.isEmpty(sb_r) && CollectionUtils.isEmpty(sb_c)) {
				return false;
			}
		}
		
		return true;
	}

	protected String getEmailAddressByIds(String ids) {
		if (ids == null || "".equalsIgnoreCase(ids.trim())) {
			return "";
		}
		String[] ids_arrys = ids.split(",");
		List<String> lst = new ArrayList<String>();
		for (String one : ids_arrys) {
			if (one != null && !"".equalsIgnoreCase(one.trim())) {
				lst.add(one);
			}
		}
		if (lst.size() > 0) {
			String[] params = new String[lst.size()];
			lst.toArray(params);
			List<Map<String, String>> emps = emailMessageService.getMessageOperationService().obtainEmailAddressByEmpIds(params);
			if (emps != null && emps.size() > 0) {
				StringBuffer sb = new StringBuffer("");
				for (String one : params) {
					for (Map<String, String> emp : emps) {
						if (StringUtils.trimToEmpty(emp.get("EMPID")).equalsIgnoreCase(one)) {
							sb.append(StringUtils.trimToEmpty(emp.get("EMPEMAIL")));
							sb.append(",");
							break;
						}
					}
				}
				if (sb.length() > 0) {
					return sb.substring(0, sb.length() - 1);
				}
			}
		}
		return "";
	}

	class SendEmailAsynThread extends Thread {
		private List<MsgWaitSendVo> vos;
		private ManualOperationParamsVo params;

		public SendEmailAsynThread(List<MsgWaitSendVo> vos, ManualOperationParamsVo params) {
			this.vos = vos;
			this.params = params;
		}

		@Override
		public void run() {
			super.run();

			long start = new Date().getTime();
			String startdate = DateUtils.getNowStr(null);

			String r = "没有邮件需要发送";

			List<MsgSendVo> exceptions = new ArrayList<MsgSendVo>();

			List<MsgSendVo> rst = new ArrayList<MsgSendVo>();

			if (vos != null && vos.size() > 0) {

				int s = 0;
				int f = 0;

				for (MsgWaitSendVo dto : vos) {
					String msg = "SUCCESS";
					List<Map<String, String>> attList = null;
					try {
						attList = null;//emailMessageService.getAttachService().getAttachments(dto.getAttids());

						// 获取邮箱的代码前置，抽取移到com.cmwa.cbp.sys.msg.adapter.impl.EmailMessageTemplateDelegate.obtainEmailAddress
						List<String> sb_r = dto.getRecipients();
						List<String> sb_c = dto.getCcs();
						if (CollectionUtils.isEmpty(sb_r)) {
							continue;
						}

						msg = EmailUtil.sendMail(params.getNickName(),params.getThirdAddressor(),dto.getTitle(), EmailUtil.EMAIL_CONTENTTYPE_HTML, dto.getContent(),sb_r.toArray(new String[sb_r.size()]) , sb_c.toArray(new String[sb_c.size()]), attList, dto.getAttFiles());

					} catch (Exception ex) {
						msg = ExceptionUtil.obtainStackTrace(ex);
						logger.error("mail send exception:", ex);
					}

					MsgSendVo msVo = new MsgSendVo();
					msVo.setWid(dto.getId());
					msVo.setEmpIds(dto.getEmpIds());
					msVo.setEmpIdsC(dto.getEmpIdsC());
					msVo.setType(dto.getType());
					msVo.setTitle(dto.getTitle());
					msVo.setContent(dto.getContent());
					msVo.setAttids(dto.getAttids());
					msVo.setPubEmailIds(dto.getPubEmailIds());
					msVo.setPubEmailIdsC(dto.getPubEmailIdsC());
					msVo.setMsgCode(params.getMsgCode());
					msVo.setRecipients(Joiner.on(",").join(dto.getRecipients()));
					msVo.setCc(Joiner.on(",").join(dto.getCcs()));

					msVo.setCreateId(dto.getCreateId());
					msVo.setCreateDate("");
					msVo.setSendId(StringUtils.trimToEmpty(params.getEmpId()));
					msVo.setMsgBatchId(dto.getId());

					if ("SUCCESS".equals(msg)) {
						msVo.setStatus("NORMAL");
						s++;
					} else {
						msVo.setStatus("EXCEPTION");
						f++;
						MsgExceptionVo eptVo = new MsgExceptionVo();
						eptVo.setException(msg);
						msVo.setException(eptVo);
						exceptions.add(msVo);
					}

					rst.add(msVo);

					/*if (attList != null && attList.size() > 0) {
						emailMessageService.getAttachService().updateAttachFilePathByAttId(attList);
					}*/

				}

				r = "成功[" + s + "]封邮件,异常[" + f + "]封邮件";

			}

			String enddate = DateUtils.getNowStr(null);
			long end = new Date().getTime();

			MsgBatchVo bv = new MsgBatchVo();
			bv.setType(operationType);
			bv.setStartTime(startdate);
			bv.setEndTime(enddate);
			bv.setElapsedTime((end - start) + "");
			bv.setRst(r);
			emailMessageService.getMsgBatchService().saveMsgBatchVo(bv);

			if (rst.size() > 0) {
				for (MsgSendVo v : rst) {
					v.setMsgBatchId(bv.getId());
					emailMessageService.getMsgSendService().create(v);
				}
			}

			if (exceptions.size() > 0) {
				for (MsgSendVo eptVo : exceptions) {

					MsgExceptionVo ept = new MsgExceptionVo();
					ept.setException(eptVo.getException().getException());
					ept.setMsgBatchId(bv.getId());
					ept.setMsgSendId(eptVo.getId());

					emailMessageService.getMsgExceptionService().create(ept);
				}
			}

		}

	}

}
